package com.beta.auth.controller;

import cn.hutool.crypto.digest.MD5;
import com.beta.auth.common.ResultVo;
import com.beta.auth.config.UserAuthCfgBean;
import com.beta.auth.constants.CacheConstans;
import com.beta.cat.service.RedissonService;
import com.beta.cat.utils.GuidUtil;
import com.beta.user.auth.center.api.response.CommonResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import vo.AccessTokenVo;

/**
 * <p>Pro.UserCenter/com.beta.auth.controller.GenerateTokenController</p>
 *
 * @description 生成Token
 * @author: zdwang
 * @date 2021/12/2 13:48
 */
@RestController
@Slf4j
@RequestMapping("token")
public class GenerateTokenController {

    @Autowired
    private RedissonService redissonService;

    @Autowired
    private UserAuthCfgBean userAuthCfgBean;

    /**
     * 根据corpId和corpSecret获取token
     *
     * @param corpId
     * @return
     */
    @RequestMapping("gettoken")
    public ResultVo<AccessTokenVo> getAccessToken(@RequestParam("corpId") String corpId) {
        // 判断corpId
        if (StringUtils.isBlank(corpId)) {
            return ResultVo.failure(CommonResultEnum.PARAMETER_HAS_NO_CORPID);
        }
        // 判断corpId是否和配置一样
        if (!MD5.create().digestHex(userAuthCfgBean.getThirdAppId(), "UTF-8").equals(corpId)) {
            return ResultVo.failure(CommonResultEnum.PARAMETER_CORPID_NOT_MATCH);
        }

        AccessTokenVo tokenVo = new AccessTokenVo();
        tokenVo.setExpireTime(7200);
        // 分布式锁key拼接
        String lockName = userAuthCfgBean.getThirdAppId() + userAuthCfgBean.getThirdSecretKey();
        try {
            /**
             * 锁粒度：全局锁，针对机构生效
             * 锁持有时间：3s
             * 锁等待时间：3s
             */
            if (!redissonService.tryLock(lockName, CacheConstans.JSAPI_TICKET_LOCK_TIME, CacheConstans.ACCESS_TOKEN_LOCK_TIME)) {
                return ResultVo.failure(CommonResultEnum.SYSTEM_IS_BUSY);
            }
            // 根据corpId查询Redis中的token
            String oldToken = redissonService.get(userAuthCfgBean.getThirdAppId());
            if (StringUtils.isNotBlank(oldToken)) {
                // 返回未过期token
                tokenVo.setAccessToken(oldToken);
                return ResultVo.success(tokenVo);
            }
            // 生成token
            String token = GuidUtil.getGuid();
            // 缓存新token，拦截器试用
            redissonService.set(userAuthCfgBean.getThirdAppId(), token, CacheConstans.EXPIRE_TIME);
            redissonService.set(token, userAuthCfgBean.getThirdAppId(), CacheConstans.EXPIRE_TIME);

            tokenVo.setAccessToken(token);
        } catch (Exception e) {
            log.error("GenerateTokenController getAccessToken 生成token失败 {}", e.getMessage(), e);
            return ResultVo.failure(CommonResultEnum.SYSTEM_IS_BUSY);
        } finally {
            redissonService.unlock(lockName);
        }
        return ResultVo.success(tokenVo);
    }
}
